package com.xd.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class HTTPConnection {
    private String username;
    private String password;
    public HTTPConnection(String username, String password) {
        this.username = username;
        this.password = password;
    }
    //建立http连接
    private HttpURLConnection openConnection(String urlStr){
        URL url;
        try {
            url = new URI(urlStr).toURL();
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            return connection;
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (URISyntaxException e) {
            e.printStackTrace();
            System.out.println("\nURL路径错误");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    //发送get请求
    public String get(String url) {
        String response = null;
        try {
            response = sendRequest(url, "GET", null, null);
            return response;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return response;
    }
    //发送post请求
    public String post(String url, String requestBody) {
        String response = null;
        try {
            response = sendRequest(url, "POST", requestBody, null);
            return response;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return response;
    }
    //发送put请求
    public String put(String url, String requestBody) {
        String response = null;
        try {
            response = sendRequest(url, "PUT", requestBody, null);
            return response;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return response;
    }
    //发送delete请求
    public String delete(String url) {
        String response = null;
        try {
            response = sendRequest(url, "DELETE", null, null);
            return response;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return response;
    }
    //发送http请求
    private String sendRequest(String url, String method, String requestBody, String authHeader)
            throws IOException, NoSuchAlgorithmException, URISyntaxException {
        //创建连接
        HttpURLConnection connection = openConnection(url);
        if(connection == null){
            return null;
        }
        //设置请求方法
        connection.setRequestMethod(method);
        //设置鉴权头
        if(authHeader != null && !authHeader.isEmpty()){
            connection.setRequestProperty("Authorization", authHeader);
        }
        //设置请求体
        if (requestBody != null && !requestBody.isEmpty()) {
            connection.setDoOutput(true);
            OutputStream os = connection.getOutputStream();
            byte[] input = requestBody.getBytes("utf-8");
            os.write(input, 0, input.length);
        }

        String response = "";
        //获取响应码
        int responseCode = connection.getResponseCode();
        if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
            if(authHeader == null || authHeader.isEmpty()){
                 //第一次鉴权，根据服务端返回的WWW-Authenticate头部信息，生成鉴权信息
                List<String> authenticateList = connection.getHeaderFields().get("WWW-Authenticate");
                if (authenticateList != null && !authenticateList.isEmpty()) {
                    String authenticateHeader = authenticateList.get(0);
                    Map<String, String> headerParams = parseAuthHeader(authenticateHeader);
                    //生成鉴权信息
                    authHeader = createDigestAuthHeader(this.username, this.password, method, url, headerParams);
                    //发送第二次带鉴权信息的请求
                    return sendRequest(url, method, requestBody, authHeader);
                }
            }
            else{
                System.out.println("鉴权失败");
            }
            response = readErrResponse(connection);
        }
        else if(responseCode == HttpURLConnection.HTTP_OK){
            response = readResponse(connection);
        }
        else{
            System.out.println("http 请求失败，状态码:" + responseCode);
            response = readErrResponse(connection);
        }
        connection.disconnect();
        return response;
    }
    //http请求成功时，读取响应数据
    private String readResponse(HttpURLConnection connection) throws IOException {
        // 读取响应内容
        BufferedReader reader = new BufferedReader(
                new InputStreamReader(connection.getInputStream(), "UTF-8"));
        String line;
        StringBuilder response = new StringBuilder();
        while ((line = reader.readLine()) != null) {
            response.append(line + "\n");
        }
        reader.close();
        return response.toString();
    }
    //http请求失败时，读取响应数据
    private String readErrResponse(HttpURLConnection connection) throws IOException{
        // 读取响应内容
        BufferedReader reader = new BufferedReader(
                new InputStreamReader(connection.getErrorStream(), "UTF-8"));
        String line;
        StringBuilder response = new StringBuilder();
        while ((line = reader.readLine()) != null) {
            response.append(line);
        }
        reader.close();
        return response.toString();
    }
    // 解析认证头部信息
    private static Map<String, String> parseAuthHeader(String authHeader) {
        Map<String, String> headerParams = new HashMap<>();
        Pattern pattern = Pattern.compile("(\\w+)=\"(.*?)\"");
        Matcher matcher = pattern.matcher(authHeader);
        while (matcher.find()) {
            headerParams.put(matcher.group(1), matcher.group(2));
        }
        return headerParams;
    }
    // 创建摘要认证头部信息
    private static String createDigestAuthHeader(String username, String password, String httpMethod, String uri,
            Map<String, String> headerParams)
            throws NoSuchAlgorithmException {
        String nonce = headerParams.get("nonce");
        String realm = headerParams.get("realm");
        String qop = headerParams.get("qop");
        String algorithm = headerParams.get("algorithm");
        int nonceCount = 1;
        String cnonce = "0wQGXJQP";
        String HA1 = md5(username + ":" + realm + ":" + password);
        String HA2 = md5(httpMethod + ":" + uri);
        String response = md5(
                HA1 + ":" + nonce + ":" + String.format("%08x", nonceCount) + ":" + cnonce + ":" + qop + ":" + HA2);
        return "Digest username=\"" + username + "\", realm=\"" + realm + "\", nonce=\"" + nonce + "\", uri=\"" + uri
                + "\", algorithm=\"" + algorithm + "\", qop=" + qop + ", response=\"" + response + "\", nc="
                + String.format("%08x", nonceCount) + ", cnonce=\"0wQGXJQP\"";
    }
    // 计算 MD5 哈希值
    private static String md5(String input) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] messageDigest = md.digest(input.getBytes(StandardCharsets.UTF_8));
        return bytesToHex(messageDigest);
    }
    // 将字节数组转换为十六进制字符串
    private static String bytesToHex(byte[] bytes) {
        StringBuilder result = new StringBuilder();
        for (byte aByte : bytes) {
            result.append(Integer.toString((aByte & 0xff) + 0x100, 16).substring(1));
        }
        return result.toString();
    }
}
